// Copyright (c) 2012, Hazen Eckert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the The University of Texas at Dallas nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT DALLAS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <fcntl.h> /* File control definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <stdio.h>
#include <unistd.h>

using namespace std;

#include "auv_driver_common/Serial.h"

Serial::Serial( const char *port )
{
	fd = open( port , O_RDWR | O_NOCTTY | O_NDELAY);

	if (fd == -1) {
		throw 19;
	} else {
		fcntl(fd, F_SETFL, 0);
	}
}

void Serial::begin( long baud )
{
	struct termios options;

	tcgetattr(fd,&options);

	switch(baud)
	{
		case 9600: 
			cfsetispeed(&options,B9600);
			cfsetospeed(&options,B9600);
			break;
		case 19200: 
			cfsetispeed(&options,B19200);
			cfsetospeed(&options,B19200);
			break;
		case 38400: 
			cfsetispeed(&options,B38400);
			cfsetospeed(&options,B38400);
			break;
		case 57600: 
			cfsetispeed(&options,B57600);
			cfsetospeed(&options,B57600);
			break;
		case 115200: 
			cfsetispeed(&options,B115200);
			cfsetospeed(&options,B115200);
			break;
		default:
			cfsetispeed(&options,B9600);
			cfsetospeed(&options,B9600);
			break;
	}

	options.c_cflag |= (CLOCAL | CREAD);

	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;

	options.c_cflag &= ~CRTSCTS;

	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	options.c_iflag &= ~(IXON | IXOFF | IXANY);

	options.c_oflag &= ~OPOST;

	options.c_cc[VMIN] = 0;
	options.c_cc[VTIME] = 20;

	tcsetattr(fd,TCSANOW,&options);
}

void Serial::end( void )
{
	close(fd);
}


int Serial::rx( void *buffer, int length )
{
	int n = read(fd, buffer, length);
	return n;
}

int Serial::tx(void *buffer, int length)
{
	int n = write(fd, buffer, length);
	return n;
}
